home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 1999 August / SGI Freeware 1999 August.iso / dist / fw_emacs.idb / usr / freeware / share / emacs / 19.34 / lisp / two-column.el.z / two-column.el
Encoding:
Text File  |  1998-10-28  |  22.4 KB  |  625 lines

  1. ;;; two-column.el --- minor mode for editing of two-column text
  2.  
  3. ;; Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
  4.  
  5. ;; Author: Daniel.Pfeiffer@Informatik.START.dbp.de, fax (+49 69) 7588-2389
  6. ;; Adapted-By: ESR, Daniel Pfeiffer
  7.  
  8. ;; Esperanto:                 English:
  9.  
  10. ;; ^Ci dosiero estas ero de GNU Emacs.     This file is part of GNU Emacs.
  11.  
  12. ;; GNU  Emacs estas libera  programaro;     GNU Emacs is free software; you can
  13. ;; vi povas disdoni ^gin kaj/a^u modifi     redistribute it and/or modify it
  14. ;; ^gin sub  la  kondi^coj  de  la  GNU     under the terms of the GNU General
  15. ;; ^Generala  Publika Licenco kiel pub-     Public License as published by the
  16. ;; likigita far la Liberprogramara Fon-     Free Software Foundation; either
  17. ;; da^jo; a^u eldono 2a,  a^u (la^u via     version 2, or (at your option) any
  18. ;; elekto) ajna posta eldono.         later version.
  19.  
  20. ;; GNU  Emacs  estas  disdonata  en  la     GNU Emacs is distributed in the hope
  21. ;; espero ke  ^gi estos utila,  sed SEN     that it will be useful, but WITHOUT
  22. ;; IA  GARANTIO;  sen e^c  la implicita     ANY WARRANTY; without even the
  23. ;; garantio  de VENDEBLECO  a^u PRETECO     implied warranty of MERCHANTABILITY
  24. ;; POR  DETERMINITA CELO.  Vidu la  GNU     or FITNESS FOR A PARTICULAR PURPOSE.
  25. ;; ^Generala Publika Licenco por plenaj     See the GNU General Public License
  26. ;; detaloj.                 for more details.
  27.  
  28. ;; Vi devus ricevinti kopion de la  GNU     You should have received a copy of
  29. ;; ^Generala  Publika  Licenco kune kun     the GNU General Public License along
  30. ;; GNU Emacs; vidu la dosieron COPYING.     with GNU Emacs; see the file
  31. ;; Alikaze skribu al la             COPYING.  If not, write to the
  32.  
  33. ;; Free Software Foundation, 59 Temple Place - Suite 330
  34. ;; Boston, MA 02111-1307, USA.
  35.  
  36.  
  37. ;;; Komentario:                 Commentary:
  38.  
  39. ;; Tiu  programaro ebligas  vin redakti     This package gives you the ability
  40. ;; dukolumnan tekston.             to edit text in a two-column format.
  41.  
  42.  
  43. ;; Vi  havas  tri eblecojn por eki tiun     You have three ways to start up this
  44. ;; mal^cefan modalon.  ^Ciu donas al vi     minor mode.  Each gives you a
  45. ;; horizontale disigatan fenestron, si-     horizontally split window similar to
  46. ;; milan al fina apareco de via teksto:     the final outcome of your text:
  47.  
  48.  
  49. ;; f2 2        asocias  novan  bufron  nomatan  associates a new  buffer called
  50. ;; C-x 6 2  same, sed kun 2C/ anta^u.         the   same,    but   with   2C/
  51. ;;                         prepended.
  52.  
  53. ;; f2 b        asocias alian bufron.  Vi povas  associates    another   buffer.
  54. ;; C-x 6 b  anka^u asocii  dataron,   se vi  This can be used to associate a
  55. ;;        ^jus anta^ue faris C-x C-f.         file if you just did C-x C-f.
  56.  
  57. ;; f2 s        disigas  jam dukolumnan tekston  splits a  two-column  text into
  58. ;; C-x 6 s  en  du   bufroj  ekde  la  nuna  two  buffers from  the  current
  59. ;;        linio,  kaj je la nuna kolumno.  line and at the current column.
  60. ;;        La    anta^uaj   signoj   (ofte  The preceding characters (often
  61. ;;        tabeligilo  a^u  |)  estas   la  tab   or  |)  are   the  column
  62. ;;        kolumna disiganto.  Linioj kiuj  separator.   Lines  that  don't
  63. ;;        ne   enhavas   ilin   ne  estas  have them  won't  be separated.
  64. ;;        disigitaj.   Kiel  la kvara kaj  Like the  fourth and fifth line
  65. ;;        la   kvina  linio se vi disigas  if  you split this  file from
  66. ;;        ^ci dataron ekde la unua  angla  the first english word.
  67. ;;        vorto.
  68.  
  69. ;; Se  vi  volas  meti  longajn liniojn     If you include long lines, i.e which
  70. ;; (ekz. programerojn) en la  kunigotan     will span both columns  (eg.  source
  71. ;; tekston,   ili  devas  esti  en   la     code), they should  be  in what will
  72. ;; estonte unua kolumno.  La alia devas     be the    first column,    with  the
  73. ;; havi vakajn linion apud ili.         associated buffer having empty lines
  74. ;;                     next to them.
  75.  
  76. ;; Averto: en Emacs kiam vi ^san^gas la     Attention:  in Emacs when you change
  77. ;; ^cefan modalon, la mal^cefaj modaloj     the major mode,  the minor modes are
  78. ;; estas  anka^u  elmemorigitaj.   Tiu-     also  purged  from  memory.  In that
  79. ;; okaze  vi devas religi la du bufrojn     case you   must  reassociate the two
  80. ;; per iu  C-x 6-ordono,  ekz. C-x 6 b.     buffers with any C-x 6-command, e.g.
  81. ;;                     C-x 6 b.
  82.  
  83. ;; Kiam   vi   estos  kontenta   de  la     When you have edited both buffers to
  84. ;; rezulto, vi kunmetos la du kolumnojn     your  content,  you merge them  with
  85. ;; per  C-x 6 1.   Se  vi  poste  vidas     C-x 6 1.  If you then see a problem,
  86. ;; problemon, vi  neniigu   la kunmeton     you undo the  merge with  C-x u  and
  87. ;; per C-x u  kaj  plue  modifu  la  du     continue   to  edit the two buffers.
  88. ;; bufrojn.  Kiam vi ne plu volas tajpi     When you  no longer  want to edit in
  89. ;; dukolumne,  vi  eliru el la mal^cefa     two  columns, you turn off the minor
  90. ;; modalo per C-x 6 d.             mode with C-x 6 d.
  91.  
  92.  
  93. ;; Aldone al dukolumna  redaktado,  ek-     In addition to two-column editing of
  94. ;; zemple por  skribi dulingvan tekston     text, for example for writing a
  95. ;; flank-al-flanke kiel ^ci tiu,  aliaj     bilingual text side-by-side as shown
  96. ;; interesaj uzoj trovitas por tiu mal-     here, other interesting uses have
  97. ;; ^cefa modalo:             been found for this minor mode:
  98.  
  99. ;; Vi povas  disigi la  kolumnojn per {+} You can separate the columns with
  100. ;; ajna   pla^ca   ^ceno   starigante {+} any string that pleases you, by
  101. ;; `2C-separator'.   Ekzemple  "{+} " {+} setting `2C-separator'.  For example
  102. ;; por  amuzi^gi.  f2 s  a^u  C-x 6 s {+} "{+} " if you'd like to have fun.
  103. ;; traktas   tiujn    kun    prefiksa {+} f2 s or C-x 6 s handles these with a
  104. ;; argumento  kiu  signifas la longon {+} prefix argument that means the
  105. ;; de tia ^ceno.              {+} desired length of such a string.
  106.  
  107.  
  108. ;; Programistoj eble ^satus la  eblecon  Programmers might like the ability
  109. ;; forspliti la komentarian kolumnon de  to split off the comment column of a
  110. ;; dosiero  kiel la sekvanta.  Vi povas  file that looks like the following.
  111. ;; rearan^gigi  la paragrafon.  La pro-  You can fill-paragraph the comment.
  112. ;; blemo  estas  ke  koda^jo tuj   lar-  The problem is, code quickly gets
  113. ;; ^gi^gas,  tiel  ke vi  bezonas   pli  rather wide, so you need to use a
  114. ;; mallar^gan   komentarian   kolumnon.  narrower comment column.  Code lines
  115. ;; Koda^jaj linioj tra `comment-column'  that reach beyond `comment-column'
  116. ;; ne problemas,  krom  ke vi ne  vidos  are no problem, except that you
  117. ;; iliajn finojn dum redaktado.         won't see their end during editing.
  118.  
  119.  
  120. ;; BEGIN                -- This is just some meaningless
  121. ;;     FOR i IN 1..10 LOOP        -- code in Ada, that runs foobar
  122. ;;       foobar( i );            -- once for each argument from one
  123. ;;     END LOOP;            -- to ten, and then we're already
  124. ;; END;                    -- through with it.
  125.  
  126. ;; Pli bone ankora^u, vi povas  pozici-     Better yet, you can put the point
  127. ;; i^gi anta^u "This",  tajpi  M-3 f2 s     before "This", type  M-3 f2 s
  128. ;; kiu  igas "-- " la separigilon inter     which makes "-- " the separator
  129. ;; senkomentaria  Ada  bufro  kaj  nur-     between a no-comments Ada buffer,
  130. ;; teksta  komentaria  bufro.   Kiam vi     and a plain text comment buffer.
  131. ;; denove  kuni^gos ilin,  ^ciu  nevaka     When you put them back together,
  132. ;; linio  de  l'  dua  kolumno   denove     every non-empty line of the 2nd
  133. ;; anta^uhavos "-- ".             column will again be preceded by
  134. ;;                     "-- ".
  135.  
  136.  
  137. ;;; Code:
  138.  
  139.  
  140. ;; Lucid patch
  141. (or (fboundp 'frame-width)
  142.     (fset 'frame-width 'screen-width))
  143.  
  144.  
  145. ;;;;; Set up keymap ;;;;;
  146.  
  147. (defvar 2C-mode-map
  148.   (let ((map (make-sparse-keymap)))
  149.     (define-key map "2" '2C-two-columns)
  150.     (define-key map [f2] '2C-two-columns)
  151.     (define-key map "b" '2C-associate-buffer)
  152.     (define-key map "s" '2C-split)
  153.     map)
  154.   "Keymap for commands for setting up two-column mode.")
  155.  
  156.  
  157.  
  158. ;;;###autoload (autoload '2C-command "two-column" () t 'keymap)
  159. (fset '2C-command 2C-mode-map)
  160.  
  161. ;;;###autoload
  162. ;; This one is for historical reasons and simple keyboards, it is not
  163. ;; at all mnemonic.  All usual sequences containing 2 were used, and
  164. ;; f2 could not be set up in a standard way under Emacs 18.
  165. (global-set-key "\C-x6" '2C-command)
  166.  
  167.  
  168. ;;;###autoload
  169. (global-set-key [f2] '2C-command)
  170.  
  171.  
  172. (defvar 2C-minor-mode-map
  173.   (let ((map (make-sparse-keymap)))
  174.     (define-key map "1" '2C-merge)
  175.     (define-key map "d" '2C-dissociate)
  176.     (define-key map "o" '2C-associated-buffer)
  177.     (define-key map "\^m" '2C-newline)
  178.     (define-key map "|" '2C-toggle-autoscroll)
  179.     (define-key map "{" '2C-shrink-window-horizontally)
  180.     (define-key map "}" '2C-enlarge-window-horizontally)
  181.     map)
  182.   "Keymap for commands for use in two-column mode.")
  183.  
  184.  
  185. (setq minor-mode-map-alist
  186.       (cons (cons '2C-mode
  187.           (let ((map (make-sparse-keymap)))
  188.             (substitute-key-definition '2C-command 2C-minor-mode-map
  189.                            map (current-global-map))
  190.             (substitute-key-definition 'enlarge-window-horizontally
  191.                            '2C-enlarge-window-horizontally
  192.                            map (current-global-map))
  193.             (substitute-key-definition 'shrink-window-horizontally
  194.                            '2C-shrink-window-horizontally
  195.                            map (current-global-map))
  196.             map))
  197.         minor-mode-map-alist))
  198.  
  199. ;;;;; variable declarations ;;;;;
  200.  
  201. ;; Markers seem to be the only buffer-id not affected by renaming a buffer.
  202. ;; This nevertheless loses when a buffer is killed.  The variable-name is
  203. ;; required by `describe-mode'.
  204. (defvar 2C-mode nil
  205.   "Marker to the associated buffer, if non-nil.")
  206. (make-variable-buffer-local '2C-mode)
  207. (put '2C-mode 'permanent-local t)
  208.  
  209.  
  210.  
  211. (setq minor-mode-alist (cons '(2C-mode " 2C") minor-mode-alist))
  212.  
  213.  
  214.  
  215. ;; rearranged, so that the pertinent info will show in 40 columns
  216. (defvar 2C-mode-line-format
  217.     '("-%*- %15b --"  (-3 . "%p")  "--%[("  mode-name
  218.       minor-mode-alist  "%n"  mode-line-process  ")%]%-")
  219.   "*Value of mode-line-format for a buffer in two-column minor mode.")
  220.  
  221.  
  222. (defvar 2C-other-buffer-hook 'text-mode
  223.   "*Hook run in new buffer when it is associated with current one.")
  224.  
  225.  
  226. (defvar 2C-separator ""
  227.   "*A string inserted between the two columns when merging.
  228. This gets set locally by \\[2C-split].")
  229. (put '2C-separator 'permanent-local t)
  230.  
  231.  
  232.  
  233. (defvar 2C-window-width 40
  234.   "*The width of the first column.  (Must be at least `window-min-width')
  235. This value is local for every buffer that sets it.")
  236. (make-variable-buffer-local '2C-window-width)
  237. (put '2C-window-width 'permanent-local t)
  238.  
  239.  
  240.  
  241. (defvar 2C-beyond-fill-column 4
  242.   "*Base for calculating `fill-column' for a buffer in two-column minor mode.
  243. The value of `fill-column' becomes `2C-window-width' for this buffer
  244. minus this value.")
  245.  
  246.  
  247.  
  248. (defvar 2C-autoscroll t
  249.   "If non-nil, Emacs attempts to keep the two column's buffers aligned.")
  250.  
  251.  
  252.  
  253. (defvar 2C-autoscroll-start nil)
  254. (make-variable-buffer-local '2C-autoscroll-start)
  255.  
  256. ;;;;; base functions ;;;;;
  257.  
  258. ;; The access method for the other buffer.  This tries to remedy against
  259. ;; lost local variables and lost buffers.
  260. (defun 2C-other (&optional req)
  261.   (or (if 2C-mode
  262.       (or (prog1
  263.           (marker-buffer 2C-mode)
  264.         (setq mode-line-format 2C-mode-line-format))
  265.           ;; The associated buffer somehow got killed.
  266.           (progn
  267.         ;; The other variables may later be useful if the user
  268.         ;; reestablishes the association.
  269.         (kill-local-variable '2C-mode)
  270.         (kill-local-variable 'mode-line-format)
  271.         nil)))
  272.       (if req (error "You must first set two-column minor mode."))))
  273.  
  274.  
  275.  
  276. ;; function for setting up two-column minor mode in a buffer associated
  277. ;; with the buffer pointed to by the marker other.
  278. (defun 2C-mode (other)
  279.   "Minor mode for independently editing two columns.
  280. This is set up for two associated buffers by the three commands bound
  281. to  \\[2C-two-columns] ,  \\[2C-associate-buffer]  and  \\[2C-split].
  282. Turning on two-column mode calls the value of the variable `2C-mode-hook',
  283. if that value is non-nil.
  284.  
  285. These buffers can be edited separately, for example with `fill-paragraph'.
  286. If you want to disable parallel scrolling temporarily, use  \\[2C-toggle-autoscroll] .
  287.  
  288. If you include long lines, i.e which will span both columns (eg.
  289. source code), they should be in what will be the first column, with
  290. the associated buffer having empty lines next to them.
  291.  
  292. Potential uses are writing bilingual texts, or editing the comments of a
  293. source code.  See the file lisp/two-column.el for detailed examples.
  294.  
  295. You have the following commands at your disposal:
  296.  
  297. \\[2C-two-columns]   Rearrange screen with current buffer first
  298. \\[2C-associate-buffer]   Reassociate buffer after changing major mode
  299. \\[shrink-window-horizontally], \\[enlarge-window-horizontally]   Shrink, enlarge current column
  300. \\[2C-associated-buffer]   Switch to associated buffer at same point
  301. \\[2C-newline] Insert newline(s) in both buffers at same point
  302. \\[2C-merge]   Merge both buffers
  303. \\[2C-dissociate]   Dissociate the two buffers
  304.  
  305. These keybindings can be customized in your ~/.emacs by `2C-mode-map',
  306. `2C-minor-mode-map' and by binding `2C-command' to some prefix.
  307.  
  308. The appearance of the screen can be customized by the variables
  309. `2C-window-width', `2C-beyond-fill-column', `2C-mode-line-format' and
  310. `truncate-partial-width-windows'."
  311.   (make-local-hook 'post-command-hook)
  312.   (add-hook 'post-command-hook '2C-autoscroll nil t)
  313.   (setq fill-column (- 2C-window-width
  314.                2C-beyond-fill-column)
  315.     mode-line-format 2C-mode-line-format
  316.     2C-mode other)
  317.   (run-hooks '2C-mode-hook))
  318.  
  319.  
  320.  
  321. ;;;###autoload
  322. (defun 2C-two-columns (&optional buffer)
  323.   "Split current window vertically for two-column editing.
  324. When called the first time, associates a buffer with the current
  325. buffer in two-column minor mode (see  \\[describe-mode] ).
  326. Runs `2C-other-buffer-hook' in the new buffer.
  327. When called again, restores the screen layout with the current buffer
  328. first and the associated buffer to it's right."
  329.   (interactive "P")
  330.   ;; first go to full width, so that we can certainly split into two windows
  331.   (if (< (window-width) (frame-width))
  332.       (enlarge-window 99999 t))
  333.   (split-window-horizontally
  334.    (max window-min-width (min 2C-window-width
  335.                   (- (frame-width) window-min-width))))
  336.   (if (2C-other)
  337.       (progn
  338.     (other-window 1)
  339.     (switch-to-buffer (2C-other))
  340.     (other-window -1)
  341.     (if 2C-autoscroll
  342.         (2C-toggle-autoscroll t)))
  343.  
  344.     (2C-mode (prog1 (point-marker)
  345.            (other-window 1)
  346.            (switch-to-buffer
  347.         (or buffer
  348.             (generate-new-buffer (concat "2C/" (buffer-name)))))
  349.            (or buffer
  350.            (run-hooks '2C-other-buffer-hook))))
  351.     
  352.     (2C-mode (prog1 (point-marker)
  353.            (other-window -1)))))
  354.  
  355.  
  356.  
  357. ;;;###autoload
  358. (defun 2C-associate-buffer ()
  359.   "Associate another buffer with this one in two-column minor mode.
  360. Can also be used to associate a just previously visited file, by
  361. accepting the proposed default buffer.
  362.  
  363. \(See  \\[describe-mode] .)"
  364.   (interactive)
  365.   (let ((b1 (current-buffer))
  366.     (b2 (or (2C-other)
  367.         (read-buffer "Associate buffer: " (other-buffer)))))
  368.     (save-excursion
  369.       (setq 2C-mode nil)
  370.       (set-buffer b2)
  371.       (and (2C-other)
  372.        (not (eq b1 (2C-other)))
  373.        (error "Buffer already associated with buffer `%s'."
  374.           (buffer-name (2C-other))))
  375.       (setq b1 (and (assq '2C-window-width (buffer-local-variables))
  376.             2C-window-width)))
  377.     ; if other buffer has a local width, adjust here too
  378.     (if b1 (setq 2C-window-width (- (frame-width) b1)))
  379.     (2C-two-columns b2)))
  380.  
  381.  
  382.  
  383. ;;;###autoload
  384. (defun 2C-split (arg)
  385.   "Split a two-column text at point, into two buffers in two-column minor mode.
  386. Point becomes the local value of `2C-window-width'.  Only lines that
  387. have the ARG same preceding characters at that column get split.  The
  388. ARG preceding characters without any leading whitespace become the local
  389. value for `2C-separator'.  This way lines that continue across both
  390. columns remain untouched in the first buffer.
  391.  
  392. This function can be used with a prototype line, to set up things.  You
  393. write the first line of each column and then split that line.  E.g.:
  394.  
  395. First column's text    sSs  Second column's text
  396.                \\___/\\
  397.             /    \\
  398.    5 character Separator      You type  M-5 \\[2C-split]  with the point here.
  399.  
  400. \(See  \\[describe-mode] .)"
  401.   (interactive "*p")
  402.   (and (2C-other)
  403.        (if (y-or-n-p (concat "Overwrite associated buffer `"
  404.                  (buffer-name (2C-other))
  405.                  "'? "))
  406.        (save-excursion
  407.          (set-buffer (2C-other))
  408.          (erase-buffer))
  409.      (signal 'quit nil)))
  410.   (let ((point (point))
  411.     ; make next-line always come back to same column
  412.     (goal-column (current-column))
  413.     ; a counter for empty lines in other buffer
  414.     (n (1- (count-lines (point-min) (point))))
  415.     chars other)
  416.     (save-excursion
  417.       (backward-char arg)
  418.       (setq chars (buffer-substring (point) point))
  419.       (skip-chars-forward " \t" point)
  420.       (make-local-variable '2C-separator)
  421.       (setq 2C-separator (buffer-substring (point) point)
  422.         2C-window-width (current-column)))
  423.     (2C-two-columns)
  424.     (setq other (2C-other))
  425.     ; now we're ready to actually split
  426.     (save-excursion
  427.       (while (not (eobp))
  428.     (if (not (and (= (current-column) goal-column)
  429.               (string= chars
  430.                    (buffer-substring (point)
  431.                          (save-excursion
  432.                            (backward-char arg)
  433.                            (point))))))
  434.         (setq n (1+ n))
  435.       (setq point (point))
  436.       (backward-char arg)
  437.       (skip-chars-backward " \t")
  438.       (delete-region point (point))
  439.       (setq point (point))
  440.       (insert-char ?\n n)
  441.       (append-to-buffer other point (progn (end-of-line)
  442.                            (if (eobp)
  443.                            (point)
  444.                          (1+ (point)))))
  445.       (delete-region point (point))
  446.       (setq n 0))
  447.     (next-line 1)))))
  448.  
  449.  
  450.  
  451.  
  452. (defun 2C-dissociate ()
  453.   "Turn off two-column minor mode in current and associated buffer.
  454. If the associated buffer is unmodified and empty, it is killed."
  455.   (interactive)
  456.   (let ((buffer (current-buffer)))
  457.     (save-excursion
  458.       (and (2C-other)
  459.        (set-buffer (2C-other))
  460.        (or (not (2C-other))
  461.            (eq buffer (2C-other)))
  462.        (if (and (not (buffer-modified-p))
  463.             (eobp) (bobp))
  464.            (kill-buffer nil)
  465.          (kill-local-variable '2C-mode)
  466.          (kill-local-variable '2C-window-width)
  467.          (kill-local-variable '2C-separator)
  468.          (kill-local-variable 'mode-line-format)
  469.          (kill-local-variable 'fill-column))))
  470.     (kill-local-variable '2C-mode)
  471.     (kill-local-variable '2C-window-width)
  472.     (kill-local-variable '2C-separator)
  473.     (kill-local-variable 'mode-line-format)
  474.     (kill-local-variable 'fill-column)))
  475.  
  476.  
  477.  
  478. ;; this doesn't use yank-rectangle, so that the first column can
  479. ;; contain long lines
  480. (defun 2C-merge ()
  481.   "Merges the associated buffer with the current buffer.
  482. They get merged at the column, which is the value of `2C-window-width',
  483. i.e. usually at the vertical window separator.  This separator gets
  484. replaced with white space.  Beyond that the value of `2C-separator' gets
  485. inserted on merged lines.  The two columns are thus pasted side by side,
  486. in a single text.  If the other buffer is not displayed to the left of
  487. this one, then this one becomes the left column.
  488.  
  489. If you want `2C-separator' on empty lines in the second column,
  490. you should put just one space in them.  In the final result, you can strip
  491. off trailing spaces with \\[beginning-of-buffer] \\[replace-regexp] [ SPC TAB ] + $ RET RET"
  492.   (interactive)
  493.   (and (> (car (window-edges)) 0)    ; not touching left edge of screen
  494.        (eq (window-buffer (previous-window))
  495.        (2C-other t))
  496.        (other-window -1))
  497.   (save-excursion
  498.     (let ((b1 (current-buffer))
  499.       (b2 (2C-other t))
  500.       string)
  501.       (goto-char (point-min))
  502.       (set-buffer b2)
  503.       (goto-char (point-min))
  504.       (while (not (eobp))
  505.     (setq string (buffer-substring (point)
  506.                        (progn (end-of-line) (point))))
  507.     (or (eobp)
  508.         (forward-char))        ; next line
  509.     (set-buffer b1)
  510.     (if (string= string "")
  511.         ()
  512.       (end-of-line)
  513.       (indent-to-column 2C-window-width)
  514.       (insert 2C-separator string))
  515.     (next-line 1)            ; add one if necessary
  516.     (set-buffer b2))))
  517.   (if (< (window-width) (frame-width))
  518.       (enlarge-window 99999 t)))
  519.  
  520. ;;;;; utility functions ;;;;;
  521.  
  522. (defun 2C-associated-buffer ()
  523.   "Switch to associated buffer."
  524.   (interactive)
  525.   (let ((line (+ (count-lines (point-min) (point))
  526.          (if (bolp) 1 0)))
  527.     (col (if (eolp) (if (bolp) 0) (current-column))))
  528.     (if (get-buffer-window (2C-other t))
  529.     (select-window (get-buffer-window (2C-other)))
  530.       (switch-to-buffer (2C-other)))
  531.     (newline (goto-line line))
  532.     (if col
  533.     (move-to-column col)
  534.       (end-of-line 1))))
  535.  
  536. (defun 2C-newline (arg)
  537.   "Insert ARG newlines in both buffers."
  538.   (interactive "P")
  539.   (save-window-excursion
  540.     (2C-associated-buffer)
  541.     (newline arg))
  542.   (newline arg))
  543.  
  544. (defun 2C-toggle-autoscroll (arg)
  545.   "Toggle autoscrolling, or set it iff prefix ARG is non-nil and positive.
  546. When autoscrolling is turned on, this also realigns the two buffers."
  547.   (interactive "P")
  548.   ;(sit-for 0)
  549.   (setq 2C-autoscroll-start (window-start))
  550.   (if (setq 2C-autoscroll (if arg
  551.                   (>= (prefix-numeric-value arg) 0)
  552.                 (not 2C-autoscroll)))
  553.       (select-window
  554.        (prog1 (selected-window)
  555.      (message "Autoscrolling is on.")
  556.      (setq arg (count-lines (point-min) (window-start)))
  557.      (if (get-buffer-window (2C-other t))
  558.          (progn
  559.            (select-window (get-buffer-window (2C-other)))
  560.            (setq arg (- arg (count-lines (point-min) (window-start))))
  561.            ;; make sure that other buffer has enough lines
  562.            (save-excursion
  563.          (insert-char ?\n
  564.                   (- arg (count-lines (window-start)
  565.                           (goto-char (point-max)))
  566.                  -1)))
  567.            (scroll-up arg)))))
  568.     (message "Autoscrolling is off.")))
  569.  
  570.  
  571.  
  572. (defun 2C-autoscroll ()
  573.   (if 2C-autoscroll
  574.       ;; catch a mouse scroll on non-selected scrollbar
  575.       (select-window
  576.        (prog1 (selected-window)
  577.      (and (consp last-command-char)
  578.           (not (eq (selected-window)
  579.                (car (car (cdr last-command-char)))))
  580.           (select-window (car (car (cdr last-command-char)))))
  581.      ;; In some cases scrolling causes an error, but post-command-hook
  582.      ;; shouldn't, and should always stay in the original window
  583.      (condition-case ()
  584.          (and (or 2C-autoscroll-start (2C-toggle-autoscroll t) nil)
  585.           (/= (window-start) 2C-autoscroll-start)
  586.           (2C-other)
  587.           (get-buffer-window (2C-other))
  588.           (let ((lines (count-lines (window-start)
  589.                         2C-autoscroll-start)))
  590.             (if (< (window-start) 2C-autoscroll-start)
  591.             (setq lines (- lines)))
  592.             (setq 2C-autoscroll-start (window-start))
  593.             (select-window (get-buffer-window (2C-other)))
  594.             ;; make sure that other buffer has enough lines
  595.             (save-excursion
  596.               (insert-char
  597.                ?\n (- lines (count-lines (window-start)
  598.                          (goto-char (point-max)))
  599.                   -1)))
  600.             (scroll-up lines)
  601.             (setq 2C-autoscroll-start (window-start))))
  602.        (error))))))
  603.  
  604.  
  605.  
  606. (defun 2C-enlarge-window-horizontally (arg)
  607.   "Make current window ARG columns wider."
  608.   (interactive "p")
  609.   (enlarge-window arg t)
  610.   (and (2C-other)
  611.        (setq 2C-window-width (+ 2C-window-width arg))
  612.        (set-buffer (2C-other))
  613.        (setq 2C-window-width (- 2C-window-width arg))))
  614.  
  615. (defun 2C-shrink-window-horizontally (arg)
  616.   "Make current window ARG columns narrower."
  617.   (interactive "p")
  618.   (2C-enlarge-window-horizontally (- arg)))
  619.  
  620.  
  621.  
  622. (provide 'two-column)
  623.  
  624. ;;; two-column.el ends here
  625.